package com.yunzhou.service.impl;

import com.yunzhou.constants.Constants;
import com.yunzhou.entity.*;
import com.yunzhou.enums.*;
import com.yunzhou.mapper.*;
import com.yunzhou.service.ForumCommentService;
import com.yunzhou.service.MinioService;
import com.yunzhou.service.QiniuyunService;
import com.yunzhou.utils.MyStringUtil;
import com.yunzhou.utils.ThreadLocalUtil;
import com.yunzhou.vo.ForumCommentVO;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import io.minio.http.Method;
import jakarta.annotation.Resource;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ForumCommentServiceImpl implements ForumCommentService {
    @Autowired
    private ForumCommentMapper forumCommentMapper;
    @Autowired
    private LikeRecordMapper likeRecordMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ForumArticleMapper forumArticleMapper;
    @Autowired
    private UserMessageMapper userMessageMapper;
    @Autowired
    private QiniuyunService qiniuyunService;
    @Autowired
    private MinioClient minioClient;
    @Resource
    private MinioService minioService;

    // 根据评论ID获取评论
    @Override
    public ForumComment getForumCommentByForumCommentId(Long commentId) {
        return forumCommentMapper.getForumCommentByForumCommentId(commentId);
    }

    // 获取文章对应的评论列表
    @Override
    public ForumCommentVO getForumCommentList(Long articleId, Integer orderType, Long userId, Integer pageNum, Integer pageSize) {
        ForumCommentVO forumCommentVO = new ForumCommentVO();

        // 获取一级评论总数
        Integer total = forumCommentMapper.getForumComment1Total(articleId);

        // 将评论改为树形结构
        // 1、获取当前页的所有一级评论
        List<ForumComment> forumComment1 = forumCommentMapper.getForumComment1(articleId, orderType, pageNum, pageSize);

        // 若当前文章没有一级评论，则直接返回即可
        if (forumComment1 == null || forumComment1.size() == 0) {
            forumCommentVO.setTotal(0);
            return forumCommentVO;
        }

        // 2、判断当前用户是否点过评论的赞（前提：用户登录）
        if (userId != null) {
            for (int i = 0; i < forumComment1.size(); i++) {
                ForumComment f = forumComment1.get(i);
                LikeRecord lr = likeRecordMapper.getLikeRecordByObjectIdAndUserIdAndOpType(
                        f.getCommentId(), userId, LikeRecordOpTypeEnum.COMMENT_LIKE.getOpType());
                if (lr != null) {
                    f.setLikeType(1); // 当前登录用户确实为评论点过赞
                    forumComment1.set(i, f);
                }
            }
        }

        // 3、获取所有一级评论对应的所有二级评论
        List<Long> parentCommentIds = forumComment1.stream().map(ForumComment::getCommentId).distinct().collect(Collectors.toList());
        List<ForumComment> forumComment2 = forumCommentMapper.getForumComment2(articleId, parentCommentIds);

        // 4、判断当前用户是否点过评论的赞（前提：用户登录）
        if (userId != null) {
            for (int i = 0; i < forumComment2.size(); i++) {
                //i:依次表示集合中的每一个索引
                ForumComment f = forumComment2.get(i);
                LikeRecord lr = likeRecordMapper.getLikeRecordByObjectIdAndUserIdAndOpType(f.getCommentId(),
                        userId, LikeRecordOpTypeEnum.COMMENT_LIKE.getOpType());
                if (lr != null) {
                    f.setLikeType(1); // 当前登录用户确实为评论点过赞
                    forumComment2.set(i, f);
                }
            }
        }

        // 5、将一级评论对应的二级评论添加到一级评论中
        // 将二级评论转换为Map，再for循环遍历一级评论，将对应的二级评论加入到一级评论中
        // 一个pCommentId（key）对应多个二级评论（value）
        // Stream流
        Map<Long, List<ForumComment>> tempMap = forumComment2.stream().collect(Collectors.groupingBy(ForumComment::getParentCommentId));
        forumComment1.forEach(item -> {
            item.setChildren(tempMap.get(item.getCommentId()));
        });

        forumCommentVO.setForumCommentList(forumComment1);
        forumCommentVO.setTotal(total);
        return forumCommentVO;
    }

    // 发表评论
    @Override
    @Transactional
    public ForumComment postComment(ForumComment forumComment, MultipartFile commentImg) {

        // 获取当前登录的用户
        Long currentUserId = ThreadLocalUtil.getCurrentUserId();
        UserInfo userInfo = userMapper.selectByUserId(currentUserId);

        forumComment.setImgPath(null);
        forumComment.setUserId(currentUserId);
        forumComment.setNickname(userInfo.getNickname());
        forumComment.setAvatar(userInfo.getAvatar());
        forumComment.setUserIpAddress(null);
        forumComment.setPostTime(LocalDateTime.now());
        forumComment.setTopType(ForumCommentTopTypeEnum.NOTOP.getTopType());
        forumComment.setLikeCount(0);
        forumComment.setStatus(ForumCommentStatusEnum.AUDIT.getStatus()); // 这里先设置为不需要审核，直接发布评论

        // 先向数据库中插入一条数据
        forumCommentMapper.insert(forumComment);

        // 再向用户消息中添加一条消息
        UserMessage userMessage = new UserMessage();
        userMessage.setReceivedUserId(forumComment.getReplyUserId());
        userMessage.setArticleId(forumComment.getArticleId());
        ForumArticle forumArticle = forumArticleMapper.getForumArticleByArticleId(forumComment.getArticleId());
        userMessage.setArticleTitle(forumArticle.getTitle());
        userMessage.setCommentId(forumComment.getCommentId());
        userMessage.setSendUserId(userInfo.getUserId());
        userMessage.setSendNickname(userInfo.getNickname());
        userMessage.setMessageType(UserMessageTypeEnum.COMMENT.getMessageType());
        userMessage.setStatus(UserMessageStatusEnum.NO_READ.getStatus());
        userMessage.setCreateTime(LocalDateTime.now());

        // 若传递过来的是文章评论，则其parentCommentId应该为null
        if (forumComment.getParentCommentId() == 0) {
            userMessage.setMessageContent("这是一条文章评论");
            // 每增加一条文章评论，文章对应的评论数+1
            forumArticleMapper.updateForumArticleCommentCountByArticleId(forumComment.getArticleId(), 1);
        } else {
            userMessage.setMessageContent("这是一条评论的评论");
        }

        // 增加用户消息
        userMessageMapper.insert(userMessage);

        // 若传递过来的评论包含图片，则将上传图片到服务器
        if(commentImg != null) {
            // 文件名
            // String extendFileName = commentImg.getOriginalFilename().substring(commentImg.getOriginalFilename().lastIndexOf(".")); //.png
            // String imgName = "评论图片/" + forumComment.getCommentId() + "/" + MyStringUtil.getUUID() + extendFileName;
            // System.out.println("文件名为：" + imgName);

            // 这里打算用UUID生成文件名
            String uuid = MyStringUtil.getUUID();
            // 文件名为UUID+文件名后缀
            String suffix = commentImg.getOriginalFilename().substring(commentImg.getOriginalFilename().lastIndexOf(".")); //.png
            String imgName = uuid + suffix;
            System.out.println("文件名为：" + imgName);

             // 上传文件到Minio
            String imagePath = null;
            try {
                imagePath = minioService.uploadFile(commentImg, Constants.MINIO_COMMENT_IMAGE_BUCKET_NAME, imgName);
            }catch (Exception e){
                throw new RuntimeException("上传文件失败");
            }

            // 将文件名更新到数据库中
            forumComment.setImgPath(imagePath);
            forumCommentMapper.update(forumComment);
        }

        return forumComment;
    }


    // 评论点赞/取消点赞
    @Override
    @Transactional
    public ForumComment doCommentLike(Long commentId) {
        UserInfo userInfo = userMapper.selectByUserId(ThreadLocalUtil.getCurrentUserId());
        ForumComment forumComment = forumCommentMapper.getForumCommentByForumCommentId(commentId);

        if (forumComment == null) {
            throw new RuntimeException("当前评论不存在");
        }

        // 0、先查看当前用户是否已经为该评论点过赞了
        LikeRecord likeRecord0 = likeRecordMapper.getLikeRecordByObjectIdAndUserIdAndOpType(
                commentId, userInfo.getUserId(), LikeRecordOpTypeEnum.COMMENT_LIKE.getOpType());
        if (likeRecord0 == null) {
            // 未查到点赞记录，说明当前登录用户未点赞过该评论
            // 1、为当前评论的点赞数+1
            forumCommentMapper.updateForumCommentLikeCountByCommentId(commentId, 1);

            // 2、增加一条系统消息
            UserMessage userMessage = new UserMessage();
            userMessage.setReceivedUserId(forumComment.getUserId());
            userMessage.setCommentId(commentId);
            userMessage.setSendUserId(userInfo.getUserId());
            userMessage.setSendNickname(userInfo.getNickname());
            userMessage.setMessageType(UserMessageTypeEnum.COMMENT_LIKE.getMessageType()); // 评论点赞
            userMessage.setStatus(UserMessageStatusEnum.NO_READ.getStatus()); // 未读
            userMessage.setCreateTime(LocalDateTime.now());
            userMessageMapper.insert(userMessage);

            // 3、增加一条点赞记录
            LikeRecord likeRecord = new LikeRecord();
            likeRecord.setOpType(LikeRecordOpTypeEnum.COMMENT_LIKE.getOpType()); // 评论点赞
            likeRecord.setObjectId(commentId);
            likeRecord.setUserId(userInfo.getUserId());
            likeRecord.setCreateTime(LocalDateTime.now());
            likeRecord.setAuthorUserId(forumComment.getUserId());
            likeRecordMapper.insert(likeRecord);

            // 4、返回给前端这条评论，以及当前登录用户是否点赞该评论
            forumComment = forumCommentMapper.getForumCommentByForumCommentId(commentId);
            forumComment.setLikeType(1); // 已点赞

        } else { // 查到点赞记录，说明当前登录用户点赞过该评论，点赞数-1并删除点赞记录
            // 该评论的点赞数-1
            forumCommentMapper.updateForumCommentLikeCountByCommentId(commentId, -1);

            // 删除点赞记录
            likeRecordMapper.deleteLikeRecordByObjectIdAndUserIdAndOpType(commentId,userInfo.getUserId(),1);

            // 当前登录用户取消点赞
            forumComment = forumCommentMapper.getForumCommentByForumCommentId(commentId);
            forumComment.setLikeType(0); // 取消点赞
        }

        return forumComment;

    }

    // 评论置顶/取消置顶
    @Override
    public void updateForumCommentTopTypeByCommentId(Long commentId) {
        forumCommentMapper.updateForumCommentTopTypeByCommentId(commentId);
    }

    // 根据用户ID获取评论列表
    @Override
    public List<ForumComment> getForumCommentListByUserId(Long userId,Integer orderType,Integer pageNum,Integer pageSize){
        return forumCommentMapper.getForumCommentListByUserId(userId,orderType,pageNum,pageSize);
    }
    // 根据用户ID获取评论总数
    @Override
    public Integer getForumCommentListTotalByUserId(Long userId){
        return forumCommentMapper.getForumCommentListTotalByUserId(userId);
    }

    // 根据接收人ID获取评论列表
    @Override
    public List<ForumComment> getForumCommentListByReplyUserId(Long replyUserId,Integer orderType,Integer pageNum,Integer pageSize){
        return forumCommentMapper.getForumCommentListByReplyUserId(replyUserId,orderType,pageNum,pageSize);
    }
    // 根据接收人ID获取评论总数
    @Override
    public Integer getForumCommentListTotalByReplyUserId(Long replyUserId){
        return forumCommentMapper.getForumCommentListTotalByReplyUserId(replyUserId);
    }

    // 根据评论ID删除评论
    public void deleteForumCommentByCommentId(Long commentId){
        forumCommentMapper.deleteForumCommentByCommentId(commentId);
    }

}
